﻿using System;
using NJabber.Stream.Elements;
using NUnit.Framework;
using System.Xml.Linq;

namespace NJabber.Stream.Elements
{
    [TestFixture]
    public class MessageStanzaTest : StanzaTestBase
    {
        private string subject = "message subject";
        private string body = "message body";
        private object parentThreadId = Guid.NewGuid();
        private object threadId = Guid.NewGuid();

        public MessageStanzaTest() : base("message", "", "")
        { }

        #region Write method test

        [Test]
        public void Write_NotEmptyBody_WritesCorrectXml()
        {
            MessageStanza stanzaElement = new MessageStanza();
            XElement expectedElement = CreateMessageXElement("", "", body);
            stanzaElement.Body = body;
            VerifyWriteOutput(expectedElement, stanzaElement);
        }

        [Test]
        public void Write_NotEmptySubject_WritesCorrectXml()
        {
            MessageStanza stanzaElement = new MessageStanza();
            XElement expectedElement = CreateMessageXElement("", subject, "");
            stanzaElement.Subject = subject;
            VerifyWriteOutput(expectedElement, stanzaElement);
        }

        [Test]
        public void Write_NotEmptyBodyAndSubject_WritesCorrectXml()
        {
            MessageStanza stanzaElement = new MessageStanza();
            XElement expectedElement = CreateMessageXElement("", subject, body);
            stanzaElement.Subject = subject;
            stanzaElement.Body = body;
            VerifyWriteOutput(expectedElement, stanzaElement);
        }

        private XElement CreateMessageXElement(string type, string subject, string body, object threadId = null, object parentThreadId = null)
        {
            XElement element = CreateStanzaXElement("message", type);
            if (!string.IsNullOrEmpty(subject)) element.Add(new XElement("subject", subject));
            if (!string.IsNullOrEmpty(body)) element.Add(new XElement("body", body));
            if(threadId != null)
            {
                element.Add(new XElement("thread", threadId));
                if (parentThreadId != null) element.Element("thread").SetAttributeValue("parent", parentThreadId);
            }
            return element;
        }

        [Test]
        public void Write_NotEmptyThreadId_WritesCorrectXml()
        {
            MessageStanza stanzaElement = new MessageStanza();
            XElement expectedElement = CreateMessageXElement("", "", "", threadId);
            stanzaElement.ThreadId = threadId;
            VerifyWriteOutput(expectedElement, stanzaElement);
        }

        [Test]
        public void Write_NotEmptyParentThreadId_WritesCorrectXml()
        {
            MessageStanza stanzaElement = new MessageStanza();
            XElement expectedElement = CreateMessageXElement("", "", "", threadId, parentThreadId);
            stanzaElement.ParentThreadId = parentThreadId;
            stanzaElement.ThreadId = threadId;
            VerifyWriteOutput(expectedElement, stanzaElement);
        }

        #endregion

        #region Equals method tests

        [Test]
        public void Equals_DifferentSubjects_ReturnsFalse()
        {
            MessageStanza message1 = new MessageStanza {Subject = "subj1"};
            MessageStanza message2 = new MessageStanza {Subject = "subj2"};

            Assert.That(message1.Equals(message2), Is.False);
        }

        [Test]
        public void Equals_SameSubjects_ReturnsTrue()
        {
            MessageStanza message1 = new MessageStanza {Subject = "subj"};
            MessageStanza message2 = new MessageStanza {Subject = "subj"};

            Assert.That(message1.Equals(message2), Is.True);
        }

        [Test]
        public void Equals_DifferentBody_ReturnsFalse()
        {
            MessageStanza message1 = new MessageStanza {Body = "Hello word"};
            MessageStanza message2 = new MessageStanza {Body = "Hollo world"};

            Assert.That(message1.Equals(message2), Is.False);
        }

        [Test]
        public void Equals_SameBody_ReturnsTrue()
        {
            MessageStanza message1 = new MessageStanza {Body = "Message"};
            MessageStanza message2 = new MessageStanza {Body = "Message"};

            Assert.That(message1.Equals(message2), Is.True);
        }

        [Test]
        public void Equals_DifferentThreadId_ReturnFalse()
        {
            MessageStanza message1 = new MessageStanza { ThreadId = "id1" };
            MessageStanza message2 = new MessageStanza { ThreadId = "id2" };

            Assert.That(message1.Equals(message2), Is.False);
        }

        [Test]
        public void Equals_SameThreadId_ReturnsTrue()
        {
            MessageStanza message1 = new MessageStanza {ThreadId = "tid"};
            MessageStanza message2 = new MessageStanza {ThreadId = "tid"};

            Assert.That(message1.Equals(message2), Is.True);
        }

        [Test]
        public void Equals_DifferentParentThreadId_ReturnsFalse()
        {
            MessageStanza message1 = new MessageStanza {ParentThreadId = "id6"};
            MessageStanza message2 = new MessageStanza {ParentThreadId = "id8"};

            Assert.That(message1.Equals(message2), Is.False);
        }

        [Test]
        public void Equals_SameParentThreadId_ReturnsTrue()
        {
            MessageStanza message1 = new MessageStanza {ParentThreadId = "id0"};
            MessageStanza message2 = new MessageStanza {ParentThreadId = "id0"};

            Assert.That(message1.Equals(message2), Is.True);
        }

        #endregion
    }
}
